Besides embedding bitmaps
in your application or accessing them from the web, Windows Phone 7
also allows you to acquire images from the built-in camera.
Your application has no
control over the camera itself. For reasons of security, your program
cannot arbitrarily snap a picture, or “see” what’s coming through the
camera lens. Your application basically invokes a standard camera
utility, the user points and shoots, and the picture is returned back to
your program.
The classes you use for this job are in the Microsoft.Phone.Tasks namespace, which contains several classes referred to as choosers and launchers. Conceptually, these are rather similar, except that choosers return data to your program but launchers do not.
The CameraCaptureTask is derived from the generic ChooserBase class which defines a Completed event and a Show method. Your program attaches a handler for the Completed event and calls Show. When the Completed event handler is called, the PhotoResult event argument contains a Stream object to the photo. From there, you already know what to do.
The SilverlightTapToShoot program contains an Image element in the content grid of its MainPage.xaml file. Here’s the entire code-behind file:
Example 1. Silverlight Project: SilverlightTapToShoot File: MainPage.xaml.cs
using System.Windows.Input; using System.Windows.Media.Imaging; using Microsoft.Phone.Controls; using Microsoft.Phone.Tasks;
namespace SilverlightTapToShoot { public partial class MainPage : PhoneApplicationPage { CameraCaptureTask camera = new CameraCaptureTask();;
public MainPage() { InitializeComponent();
camera.Completed += OnCameraCaptureTaskCompleted; }
protected override void OnManipulationStarted(ManipulationStartedEventArgs args) { camera.Show();
args.Complete(); args.Handled = true; base.OnManipulationStarted(args); }
void OnCameraCaptureTaskCompleted(object sender, PhotoResult args) { if (args.TaskResult == TaskResult.OK) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(args.ChosenPhoto); img.Source = bmp; } } } }
|
You can run this program on the phone emulator. When you tap the emulator screen, the call to Show
causes the camera task to start up and you’ll navigate to a page that
resembles the actual camera. You can “shoot” a photo by tapping an icon
in the upper-right corner of the screen. The simulated “photo” just
looks like a large white square with a small black square inside one of
the edges. Then you need to click the Accept button.
You can also run this program
on the phone itself, of course, but not when the phone is tethered to
the PC and the Zune software is running. After deploying the application
to the phone using Visual Studio, you’ll need to close the Zune
software before testing the program.
If you need to use Visual
Studio to debug an application that uses the camera while the
application is running on the phone, you can use a little command-line
program called WPDTPTConnect32.exe or WPDTPTConnect64.exe (depending on
whether your development machine is 32-bit or 64-bit). These program is
an alternative to the Zune software for allowing the Visual Studio
debugger to control your program as it’s running on the phone. The Zune
software must be closed before you use these programs.
In either case, when you press the Accept button, the camera goes away and the program’s OnCameraCaptureTaskCompleted method takes over. It creates a BitmapImage object, sets the input stream from args.ChoosenPhoto, and then sets the BitmapImage object to the Image element, displaying the photo on the screen.
The whole process seems fairly
straightforward. Conceptually it seems as if the program is spawning
the camera process, and then resuming control when that camera process
terminates.
However, the Windows Phone 7
documentation that I’m consulting warns that this is not the case.
There’s something else going on that is not so evident at first and
which you will probably find somewhat unnerving.
When the SilverlightTapToShoot program calls the Show method on the CameraCaptureTask object, the SilverlightTapToShoot program is terminated. (Not immediately, though. The OnManipulationStarted
method is allowed to return back to the program, and a couple other
events are fired, but then the program is definitely terminated.)
The camera utility then runs.
When the camera utility has done its job, the SilverlightTapToShoot
program is re-executed. It’s a new instance of the program. The program
starts up from the beginning, the MainPage constructor is eventually called which sets the Completed event of the CameraCaptureTask to OnCameraCaptureTaskCompleted, and then that method is called.
For these reasons, the documentation advises that when you use a chooser or launcher such as CameraCaptureTask, the object must be defined as a field, and the handler for the Completed event must be attached
in the program’s constructor, and as late in the constructor as
possible because once the handler is attached when the program starts up
again, it will be called.
This termination and re-execution of your program is a characteristic of Windows Phone 7 programming call tombstoning.
When the program is terminated as the camera task begins, sufficient
information is retained by the phone operating system to start the
program up again when the camera finishes. However, not enough
information is retained to restore the program entirely to its
pre-tombstone state. That’s your responsibility.
Running a launcher or chooser is one way tombstoning
can occur. But it also occurs when the user leaves your program by
pressing the Start button on the phone. Eventually the user could return
to your program by pressing the Back button, and your program needs to
be re-executed from its tombstoned state. Tombstoning also takes place
when a lack of activity on the phone causes it to go into a lock state.
Tombstoning does not
occur when your program is running and the user presses the Back
button. The Back button simply terminates the program normally.
When tombstoning
occurs, obviously you’ll want to save some of the state of your program
so you can restore that state when the program starts up again, and
obviously Windows Phone 7 has facilities to help you out.